package com.yykj.user.center.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.service.RedisService;
import com.yykj.common.util.GsonUtil;
import com.yykj.common.util.LocalRequestUtil;
import com.yykj.common.util.LocalStringUtil;
import com.yykj.common.vo.PageData;
import com.yykj.hospital.client.dto.DoctorDTO;
import com.yykj.hospital.client.feign.HospitalServerFeignClient;
import com.yykj.message.center.client.feign.MessageFeignClient;
import com.yykj.user.center.server.dto.InspectDTO;
import com.yykj.user.center.server.dto.InspectInfoDTO;
import com.yykj.user.center.server.dto.UserLoginInfo;
import com.yykj.user.center.server.emun.OrderType;
import com.yykj.user.center.server.form.AppointmentInspectForm;
import com.yykj.user.center.server.form.InspectApplyForm;
import com.yykj.user.center.server.form.PatientAppointmentInspectForm;
import com.yykj.user.center.server.model.Inspect;
import com.yykj.user.center.server.model.Patient;
import com.yykj.user.center.server.model.PatientCardInfo;
import com.yykj.user.center.server.repository.InspectRepository;
import com.yykj.user.center.server.repository.patient.PatientCardInfoRepository;
import com.yykj.user.center.server.repository.patient.PatientRepository;
import com.yykj.user.center.server.service.InspectService;
import com.yykj.user.center.server.service.patient.PaymentService;
import com.yykj.user.center.server.utils.DateUtil;
import com.yykj.user.center.server.utils.OrderUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author chenl
 * @version 1.0
 * @date 2021/11/9 19:31
 */
@Service
@Slf4j
public class InspectServiceImpl implements InspectService {
    @Autowired
    private InspectRepository inspectRepository;
    @Autowired
    private RedisService redisService;
    @Autowired
    private PatientCardInfoRepository patientCardInfoRepository;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private PatientRepository patientRepository;
    @Autowired
    private HospitalServerFeignClient hospitalServerFeignClient;

    @Autowired
    private MessageFeignClient messageFeignClient;
    @Override
    public Boolean apply(InspectApplyForm inspectApplyForm) {
        Inspect inspect = new Inspect();
        BeanUtils.copyProperties(inspectApplyForm, inspect);
        String patientCardId = inspect.getPatientCardId();
        PatientCardInfo patientCardInfo = patientCardInfoRepository.findById(patientCardId).orElse(null);
        if(patientCardInfo!=null){
           /* String token = LocalRequestUtil.getToken();
            JSONObject jsonObject= JSON.parseObject(redisService.get(token));
            log.info("jsonObject===>{}",JSON.toJSONString(jsonObject));
            log.info("token===>{}",jsonObject.get("token"));
            log.info("doctorId===>{}",jsonObject.get("doctorId"));
            String userId = jsonObject.getString("doctorId");*/
            String id = LocalStringUtil.getUUID();
            inspect.setId(id);
            inspect.setValid(24);
            inspect.setState(1);
            inspect.setAge(patientCardInfo.getAge());
            inspect.setBirthday(patientCardInfo.getBirthday());
            inspect.setRelation(patientCardInfo.getRelation());
            inspect.setSex(patientCardInfo.getSex());
            inspect.setAccountId(inspectApplyForm.getAccountId());

            DoctorDTO doctorDTO = hospitalServerFeignClient.info(inspectApplyForm.getAppDoctorId());
            if(doctorDTO == null || StringUtils.isEmpty(doctorDTO.getTencentAccountId())){
                throw new NormalException(ResultEnums._2210);
            }

            inspect.setDoctorTencentAccountId(doctorDTO.getTencentAccountId());
            Optional<Patient> patient = this.patientRepository.findById(inspectApplyForm.getAccountId());
            if(patient.isPresent()){
                inspect.setPatientTencentAccountId(patient.get().getTencentAccountId());
            }else{
                throw new NormalException(ResultEnums._2211);
            }

            Integer code = inspectApplyForm.getOrderType() == 1 ? OrderType.JIAN_CHA_DING_DAN.getCode() : OrderType.JIAN_YAN_DING_DAN.getCode();
            inspect.setOrderNo(OrderUtil.getOrderNo(inspectApplyForm.getHospitalId(), code));
            inspectRepository.save(inspect);
            inspect = inspectRepository.findById(id).orElse(null);
            InspectInfoDTO inspectInfoDTO = new InspectInfoDTO();
            BeanUtils.copyProperties(inspect,inspectInfoDTO);
            inspectInfoDTO.setCreateTime(DateUtil.dateTime2StringDateTime(inspect.getCreateTime()));
            //发送检查检验的消息通知
            Map dataMap = new HashMap();
            dataMap.put("type",3);
            dataMap.put("data",inspectInfoDTO);
            paymentService.sendPayedMsg(inspect.getDoctorTencentAccountId(),inspect.getPatientTencentAccountId(), JSON.toJSONString(dataMap,SerializerFeature.WriteNullStringAsEmpty),1);
            Optional<Patient> optional = this.patientRepository.findById(inspect.getAccountId());
            if(optional.isPresent()){
                messageFeignClient.smsPatientExamine(optional.get().getMobile(),inspect.getAppDoctorName(), inspect.getSeeDeptName(), inspect.getSeeDeptName());
            }
        }

        return true;
    }

    @Override
    public InspectDTO info(String id) {
        Inspect inspect = inspectRepository.findById(id).orElse(null);
        InspectDTO inspectDTO = new InspectDTO();
        if (inspect != null) {
            BeanUtils.copyProperties(inspect, inspectDTO);
        }
        return inspectDTO;
    }

    @Override
    public PageData<InspectDTO> inspectList(Integer current, Integer size, String startDate, String endDate, String patientName, String itemName, Integer orderType, String patientCardId, Integer state,String doctorId,Integer hospitalId) {
        Pageable pageable = PageRequest.of(current, size, Sort.by(Sort.Order.desc("createTime")));
        Page<Inspect> list = inspectRepository.findAll(new Specification<Inspect>() {
            @Override
            public Predicate toPredicate(Root<Inspect> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                predicateList.add(builder.equal(root.get("hospitalId"), hospitalId));
                if(StringUtils.isNotBlank(doctorId)){
                    predicateList.add(builder.equal(root.get("appDoctorId"), doctorId));
                }else{
                    String token = LocalRequestUtil.getToken();
                    UserLoginInfo userLoginInfo = GsonUtil.fromJson(redisService.get(token), UserLoginInfo.class);
                    String userId = userLoginInfo.getUserId();
                    predicateList.add(builder.equal(root.get("accountId"), userId));
                }
                if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
                    LocalDate start = DateUtil.stringDate2Date(startDate);
                    LocalDate end = DateUtil.stringDate2Date(endDate);
                    predicateList.add(builder.between(root.get("createTime"), start, end));
                }
                if (StringUtils.isNotBlank(patientName)) {
                    predicateList.add(builder.like(root.get("patientName"), patientName));
                }

                if (StringUtils.isNotBlank(itemName)) {
                    predicateList.add(builder.like(root.get("itemNames"), itemName));
                }

                if (orderType != null) {
                    predicateList.add(builder.equal(root.get("orderType"), orderType));
                }

                if (StringUtils.isNotBlank(patientCardId)) {
                    predicateList.add(builder.equal(root.get("patientCardId"), patientCardId));
                }

                if (state != null) {
                    predicateList.add(builder.equal(root.get("state"), state));
                }


                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        }, pageable);
        List<InspectDTO> inspectDTOS = new ArrayList<>();
        for (Inspect inspect : list.getContent()) {
            InspectDTO inspectDTO = new InspectDTO();
            BeanUtils.copyProperties(inspect, inspectDTO);
            inspectDTO.setCreateTime(DateUtil.dateTime2StringDateTime(inspect.getCreateTime()));
            inspectDTO.setUpdateTime(DateUtil.dateTime2StringDateTime(inspect.getUpdateTime()));
            inspectDTO.setAttention(inspect.getAttention() == null ? "" : inspect.getAttention());
            inspectDTOS.add(inspectDTO);
        }
        PageData page = new PageData();
        page.setList(inspectDTOS);
        page.setCurrentPage(current);
        page.setPageSize(size);
        page.setTotalCount(list.getTotalElements());
        return page;
    }

    @Override
    public Boolean appointment(AppointmentInspectForm appointmentInspectForm) {
        Inspect inspect = inspectRepository.findById(appointmentInspectForm.getId()).orElse(null);
        if (inspect != null) {
            inspect.setVisitTime(appointmentInspectForm.getLocalDateTime());
            inspect.setState(3);
            inspectRepository.save(inspect);
        }
        return true;
    }

    @Override
    public Boolean removeAppointment(AppointmentInspectForm appointmentInspectForm) {
        Inspect inspect = inspectRepository.findById(appointmentInspectForm.getId()).orElse(null);
        if (inspect != null) {
            LocalDateTime localDateTime = appointmentInspectForm.getLocalDateTime();
//            LocalDateTime localDateTime = DateUtil.stringDateTime2DateTime(strLocalTime);
            inspect.setRemoveTime(localDateTime);
            inspect.setState(5);
            inspectRepository.save(inspect);
        }
        return true;
    }

    @Override
    public Boolean patientAppointment(PatientAppointmentInspectForm patientAppointmentInspectForm) {
        Inspect inspect = inspectRepository.findById(patientAppointmentInspectForm.getId()).orElse(null);
        if (inspect != null) {
            inspect.setState(2);
            inspectRepository.save(inspect);
        }
        return true;
    }

    @Override
    public void complete() {
        List<Inspect> inspects = inspectRepository.findAllByStateAndVisitTimeBefore(3, LocalDateTime.now());
        List<Inspect> inspectList=new ArrayList<>();
        for (Inspect inspect : inspects) {
            inspect.setState(4);
            inspectList.add(inspect);
        }
        inspectRepository.saveAll(inspectList);
    }

    @Override
    public void remove() {
        int[] states = {1,2};
        List<Inspect> inspects = inspectRepository.findAllByStateIn(states);
        List<Inspect> inspectList=new ArrayList<>();
        for (Inspect inspect : inspects) {
            LocalDateTime localDateTime = inspect.getCreateTime().minusDays(inspect.getValid());
            if(inspect.getCreateTime().isAfter(localDateTime)){
                inspect.setState(5);
                inspectList.add(inspect);
            }
        }
        inspectRepository.saveAll(inspectList);
    }
}
